package com.xxlie.auth.service.impl;

import com.xxlie.core.model.Page;
import com.xxlie.auth.domain.Role;
import com.xxlie.auth.domain.User;
import com.xxlie.auth.repository.UserRepository;
import com.xxlie.auth.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
 * DatabaseUserService
 *
 * @author xxlie.com
 * @since 2017/7/30
 */
@Service
@Transactional(readOnly = true)
public class UserServiceImpl implements UserService {

    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;

    @Autowired
    public UserServiceImpl(UserRepository userRepository, PasswordEncoder passwordEncoder) {
        this.userRepository = userRepository;
        this.passwordEncoder = passwordEncoder;
    }

    @Override
    public Page<User> findAll(Page<User> page, User user) {
        Sort sort = new Sort(Sort.Direction.DESC, "updateDate");
        PageRequest pageRequest = new PageRequest(page.getPageNumber(), page.getPageSize(), sort);
        org.springframework.data.domain.Page<User> dictPage = userRepository.findAll((root, query, builder) -> {

            List<Predicate> predicates = new ArrayList<>();
            if (StringUtils.isNotEmpty(user.getName())) {
                predicates.add(builder.like(root.get("name"), "%" + user.getName() + "%"));
            }
            if (StringUtils.isNotEmpty(user.getUsername())) {
                predicates.add(builder.like(root.get("username"), "%" + user.getUsername() + "%"));
            }
            if (StringUtils.isNotEmpty(user.getNickName())) {
                predicates.add(builder.like(root.get("nickName"), "%" + user.getNickName() + "%"));
            }
            if (StringUtils.isNotEmpty(user.getPhone())) {
                predicates.add(builder.like(root.get("phone"), "%" + user.getPhone() + "%"));
            }
            if (StringUtils.isNotEmpty(user.getEmail())) {
                predicates.add(builder.equal(root.get("email"), user.getEmail()));
            }
            if (user.getInviterId() != null) {
                predicates.add(builder.equal(root.get("inviterId"), user.getInviterId()));
            }
            predicates.add(builder.like(root.get("delFlag"), Role.DEL_FLAG_NORMAL));
            Predicate[] predicatesArray = new Predicate[predicates.size()];
            predicates.toArray(predicatesArray);
            return builder.and(predicatesArray);

        }, pageRequest);

        return new Page<User>(dictPage);
    }

    @Override
    public Optional<User> getByUsername(String username) {
        return this.userRepository.findByUsername(username);
    }

    @Override
    public Optional<User> findByPhone(String phone) {
        return this.userRepository.findByPhone(phone);
    }

    @Transactional()
    @Override
    public void updateUserLoginInfo(String ip, Long id) {
        userRepository.updateLoginInfo(ip, new Date(), id);
    }

    @Transactional()
    @Override
    public void updatePasswordById(Long id, String newPassword) {

        userRepository.updatePasswordById(passwordEncoder.encode(newPassword), id);
    }

    @Transactional()
    @Override
    public void save(User user) {
        userRepository.save(user);
    }

    @Transactional()
    @Override
    public void delete(Long id) {
        userRepository.deleteById(id);
    }

    @Override
    public User findOne(Long id) {
        return userRepository.findOne(id);
    }

    @Override
    public int countByInviterId(long id) {
        return this.userRepository.countByInviterId(id);
    }
}
